/*Copyright (C) 2009 - 2011 MASSART GAUTHIER and Careil Baptiste

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "../headers.h"

/* Menu principal de l'éditeur de niveaux
*/
void pou_menu_level_editor() {
	int choix;

	do {
		clear();
		choix = afficher_menu_jeu("Editer un niveau existant\n"
															"Créer un niveau dans un pack de niveau existant\n"
															"Créer un nouveau pack de niveaux\n"
															"Retour\n",
															TITRE_POUSSE_CAISSE);

		if(choix == 1) {
			pou_choose_level_pack_to_edit();
		}
		else if(choix == 2) {
			pou_create_level();
		}
		else if(choix == 3) {
			pou_create_level_pack();
		}
	}
	while(choix != 4);
}

/* Permet de choisir le pack de niveaux à éditer
*/
void pou_choose_level_pack_to_edit() {
	char filename[256];
	FILE *level_pack;

	clear();
	afficher_titre(TITRE_POUSSE_CAISSE);
	CSLP_ColorText(CT);
	addstr("Entrez le nom du pack de niveau : ");
	refresh();
	lire(filename, 256);
	level_pack = fopen(filename, "r");

	if(level_pack == NULL) {
		CSLP_ColorText(COL_ERREUR);
		addstr("\nErreur : Impossible d'ouvrir le pack de niveau.");
		getch();
	}
	else {
		pou_choose_level_to_edit(level_pack, filename);
	}
}

/* Permet de choisir le niveau à éditer
*/
void pou_choose_level_to_edit(FILE *file, char *filename) {
	POU_CASE_T matrix[POU_MAT_X][POU_MAT_Y];
	POU_INF_T inf;
	int choix, nb_levels;
	char lvl_name[50], *level_list = NULL, *level_string = NULL;
	char author_name[50], *author_list = NULL;

	nb_levels = pou_get_level_list(file, &level_list, &author_list);

	if(!nb_levels) {
		fclose(file);
		CSLP_ColorText(COL_ERREUR);
		addstr("\nLe format du fichier est invalide.");
		getch();
		return;
	}

	level_list = realloc(level_list, (strlen(level_list) + strlen("Retour\n") + 1) * sizeof(char));
	strcat(level_list, "Retour\n");
	clear();
	choix = afficher_menu(level_list, "Choisissez le niveau à éditer :", TITRE_POUSSE_CAISSE);

	if(choix <= nb_levels) {
		pou_init_to_default(matrix, &inf);

		if(pou_parse_file(file, choix, matrix, &inf)) {
			CSLP_ColorText(COL_ERREUR);
			addstr("\nErreur : Le format du niveau est invalide.");
			getch();
		}
		else {
			inf.coups = EMPTY_CONTAINER;
			inf.nb_deplacements = 0;

			if(pou_level_editor(matrix, &inf)) {
				clear();
				fclose(file);
				file = NULL;
				pou_edit_level_info(lvl_name, author_name, 50);
				level_string = pou_level_to_string(matrix, author_name, lvl_name);
				if(level_string == NULL) {
					CSLP_ColorText(COL_ERREUR);
					addstr("\nMemoire insufisante.");
					addstr("\nLa sauvegarde a echouee.");
					getch();
				}
				else {
					if(fichier_merge(POU_DEST_TEMP_FILENAME,
													 filename,
													 level_string,
													 (choix - 1) * 22,
													 false)) {
						CSLP_ColorText(COL_ERREUR);
						addstr("\nImposible de fusioner le niveau édité avec le pack de niveaux.");
						addstr("\nLa sauvegarde a échouée");
						getch();
					}
					else if(remove(filename)) {
						CSLP_ColorText(COL_ERREUR);
						addstr("\nImpossible de supprimer le fichier d'origine, veuillez procéder manuellement.");
						getch();
					}
					else {
						if(rename(POU_DEST_TEMP_FILENAME, filename)) {
							CSLP_ColorText(COL_ERREUR);
							addstr("\nLe renomage du fichier temporaire a échoué.");
							addstr("\nVeuillez procéder manuellement.");
							getch();
						}
						else {
							CSLP_ColorText(COLOR_GREEN);
							addstr("\nLa sauvegarde a réussie.");
							getch();
						}
					}
					free(level_string);
				}
			}
		}
	}

	free(level_list);
	free(author_list);

	if(file != NULL) {
		fclose(file);
	}
}

/* Permet de créer un level
*/
void pou_create_level() {
	POU_CASE_T matrix[POU_MAT_X][POU_MAT_Y];
	POU_INF_T inf;
	char author_name[50], lvl_name[50];
	char lvl_pack_filename[256];
	int choix;
	bool loop = true;

	pou_init_to_default(matrix, &inf);

	if(pou_level_editor(matrix, &inf)) {
		pou_edit_level_info(lvl_name, author_name, 50);

		while(loop == true) {
			clear();
			afficher_titre(TITRE_POUSSE_CAISSE);
			CSLP_ColorText(CT);
			addstr("\n\nEntrez le nom du pack de niveaux où sauvegarder le niveau : ");
			lire(lvl_pack_filename, 256);

			if(fichier_existe(lvl_pack_filename) == false) {
				clear();
				choix = afficher_menu("Oui\nNon\n", "Ce pack de niveaux n'existe pas, le créer?", TITRE_POUSSE_CAISSE);

				if(choix == 1) {
					if(fichier_creer(lvl_pack_filename)) {
						CSLP_ColorText(COL_ERREUR);
						addstr("\n\nLa création du fichier a échoué.");
						getch();
					}
					else {
						loop = false;
					}
				}
			}
			else {
				loop = false;
			}
		}

		if(pou_append_to_lvl_pack(lvl_pack_filename, matrix, lvl_name, author_name)) {
			addstr("\n\nLa sauvegarde a échoué.");
			getch();
		}
		else {
			CSLP_ColorText(COLOR_GREEN);
			addstr("\n\nNiveau sauvegardé avec succès.");
			getch();
		}
	}
}

/* Permet de demander le nom de l'auteur et le nom du niveau à
** l'utilisateur.
*/
void pou_edit_level_info(char *lvl_name, char *author_name, size_t len) {
	bool loop = true;

	clear();
	afficher_titre(TITRE_POUSSE_CAISSE);
	CSLP_ColorText(CT);
	addstr("Entrez le nom de l'auteur du niveau :\n");
	get_player_name(0, prenom);
	strcpy(author_name, prenom);
	addstr("\n\n");

	while(loop == true) {
		clear_line();
		addstr("Entrez le nom du niveau : ");
		lire(lvl_name, len);

		if(lvl_name[0] != '\0') {
			loop = false;
		}
	}
}

/* Permet d'ajouter un niveau à la fin d'un pack
*/
int pou_append_to_lvl_pack(const char *lvl_pack_filename, POU_CASE_T matrix[POU_MAT_X][POU_MAT_Y], const char *lvl_name, const char *author_name) {
	FILE *lvl_pack;

	lvl_pack = fopen(lvl_pack_filename, "a");

	if(lvl_pack == NULL) {
		CSLP_ColorText(COL_ERREUR);
		addstr("\nLe pack de niveaux n'a pas pu être ouvert.");
		return 1;
	}

	pou_save_level(lvl_pack, matrix, author_name, lvl_name);
	fclose(lvl_pack);
	return 0;
}

/* Permet de créer un pack de niveaux
*/
int pou_create_level_pack() {
	int retval = 0;
	char filename[256];
	bool loop = true;

	while(loop) {
		clear();
		afficher_titre(TITRE_POUSSE_CAISSE);
		CSLP_ColorText(CT);
		addstr("\nChoisissez le nom du nouveau pack de niveau (\"annuler\" pour annuler la création) : ");
		lire(filename, 256);
		addch('\n');

		if(strcmp(filename, "annuler") == 0) {
			loop = false;
			retval = 1;
		}
		else {
			if(fichier_existe(filename) == true) {
				CSLP_ColorText(COL_ERREUR);
				addstr("Le fichier existe déjà.");
				getch();
			}
			else {
				if(fichier_creer(filename)) {
					CSLP_ColorText(COL_ERREUR);
					addstr("Impossible de créer le fichier.");
					getch();
				}
				else {
					loop = false;
					retval = 0;
					CSLP_ColorText(COLOR_GREEN);
					addstr("Fichier créé avec succès.");
					getch();
				}
			}
		}
	}

	return retval;
}

/* Boucle principale de l'éditeur. Ses deux arguments
** doivent être corectement initialisé.
*/
int pou_level_editor(POU_CASE_T matrix[POU_MAT_X][POU_MAT_Y], POU_INF_T *inf) {
	bool loop = true;
	int key, choix, retval = 0;
	IPoint cursor_pos;

	curs_set(0);
	pou_display_editor(matrix, inf);
	cursor_pos.x = 1;
	cursor_pos.y = 1;
	move(cursor_pos.y + POU_MAT_ORG_Y, cursor_pos.x + POU_MAT_ORG_X);
	curs_set(1);
	refresh();

	while(loop) {
		key = getch();

		if(key == POU_KEY_QUIT) {
			clear();
			choix = afficher_menu("Sauvegarder et quitter\n"
														"Quitter sans sauvegarder\n"
														"Annuler\n",
														"Que voulez-vous faire?\n",
														TITRE_POUSSE_CAISSE);

			if(choix == 1) {
				loop = false;
				retval = 1;
			}
			else if(choix == 2) {
				loop = false;
				retval = 0;
			}
			else {
				pou_display_editor(matrix, inf);
				curs_set(1);
			}
		}
		else if(key == touche_haut
						|| key == touche_bas
						|| key == touche_droite
						|| key == touche_gauche) {
			pou_move_cursor(key, &cursor_pos);
		}
		else {
			pou_edit_matrix(matrix, key, &cursor_pos, inf);
		}
	}

	curs_set(0);
	return retval;
}

/* Permet de modifier la position du curseur sous ordre
** du joueur
*/
void pou_move_cursor(int key, IPoint *cursor_pos) {
	if(key == touche_bas) {
		if(cursor_pos->y < POU_MAT_Y - 2) {
			cursor_pos->y++;
		}
	}
	else if(key == touche_haut) {
		if(cursor_pos->y > 1) {
			cursor_pos->y--;
		}
	}
	else if(key == touche_droite) {
		if(cursor_pos->x < POU_MAT_X - 2) {
			cursor_pos->x++;
		}
	}
	else if(key == touche_gauche) {
		if(cursor_pos->x > 1) {
			cursor_pos->x--;
		}
	}

	move(cursor_pos->y + POU_MAT_ORG_Y, cursor_pos->x + POU_MAT_ORG_X);
}

/* Permet d'éditer la matrice sous ordre du joueur
*/
void pou_edit_matrix(POU_CASE_T matrix[POU_MAT_X][POU_MAT_Y], int key, IPoint *cursor_pos, POU_INF_T *inf) {
	POU_CASE_T *cel;

	cel = &matrix[cursor_pos->x][cursor_pos->y];

	if(key == POU_KEY_ECAISSE && *cel != POU_CAISSE) {
		if(*cel == POU_JOUEUR) {
			inf->pos_joueur.x = -1;
			inf->pos_joueur.y = -1;
		}
		else if(*cel == POU_TROU) {
			inf->nb_trous--;
		}

		*cel = POU_CAISSE;
		inf->nb_caisses++;
	}
	else if(key == POU_KEY_EJOUEUR && *cel != POU_JOUEUR) {
		if(*cel == POU_TROU) {
			inf->nb_trous--;
		}
		else if(*cel == POU_CAISSE) {
			inf->nb_caisses--;
		}

		*cel = POU_JOUEUR;

		if(inf->pos_joueur.x >= 0 && inf->pos_joueur.y >= 0) {
			matrix[inf->pos_joueur.x][inf->pos_joueur.y] = POU_VIDE;
			save_cursor_pos();
			pou_refresh_case(&inf->pos_joueur, POU_VIDE);
			restore_cursor_pos();
		}

		inf->pos_joueur = *cursor_pos;
	}
	else if(key == POU_KEY_EMUR) {
		if(*cel == POU_JOUEUR) {
			inf->pos_joueur.x = -1;
			inf->pos_joueur.y = -1;
		}
		else if(*cel == POU_CAISSE) {
			inf->nb_caisses--;
		}
		else if(*cel == POU_TROU) {
			inf->nb_trous--;
		}

		*cel = POU_MUR;
	}
	else if(key == POU_KEY_ETROU && *cel != POU_TROU) {
		if(*cel == POU_JOUEUR) {
			inf->pos_joueur.x = -1;
			inf->pos_joueur.y = -1;
		}
		else if(*cel == POU_CAISSE) {
			inf->nb_caisses--;
		}

		*cel = POU_TROU;
		inf->nb_trous++;
	}
	else if(key == POU_KEY_EVIDE) {
		if(*cel == POU_JOUEUR) {
			inf->pos_joueur.x = -1;
			inf->pos_joueur.y = -1;
		}
		else if(*cel == POU_CAISSE) {
			inf->nb_caisses--;
		}
		else if(*cel == POU_TROU) {
			inf->nb_trous--;
		}

		*cel = POU_VIDE;
	}
	else {
		return;
	}

	pou_refresh_case(NULL, *cel);
	curs_set(0);
	pou_refresh_editor_inf(inf);
	pou_move_cursor(key, cursor_pos);
	curs_set(1);
}
